"""

Copyright (C) 2011-2012 BIAGINI Nathan

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

"""

import pygame
from pygame.locals import *
from particle import Particle
from elementtree.ElementTree import ElementTree
import random, copy

class Emitter():
	"""

	Position where are created all the new particles.

	"""
	
	def __init__(self):
		self.x, self.y = 0, 0

	def setLocation(self, loc):
		"""

		Change the current emitter location by the given location.

		@loc L{Tuple} : new location of the emitter

		"""

		self.x, self.y = loc 

	def getLocation(self):
		return self.x, self.y

class ParticleEngine():
	"""

	Generates particles.

	"""

	def __init__(self, particles_xml_file):
		self.particles_xml_file = particles_xml_file
		self.particle_templates = []
		self.particles = []
		self.emitter = Emitter()

		self.loadParticleTemplatesFromXML()

	def loadParticleTemplatesFromXML(self):
		"""

		Load the particles from the given XML file.

		"""

		tree = ElementTree()

		tree.parse(self.particles_xml_file)
		
		root = tree.getroot()

		for particle in root.getchildren():
			life_time = speed = surface_data = scale = color = alpha = end_color = color_change_freq = end_scale = scale_change_freq = end_alpha = alpha_change_freq = 0
			for prp in particle.getchildren():
				attribs = prp.attrib

				if attribs['id'] == 'life_frames':
					life_frames = int(attribs['value'])

				elif attribs['id'] == 'speed':
					speed = int(attribs['value'])

				elif attribs['id'] == 'surface':
					surface_data = self.createParticleSurface(attribs)

				elif attribs['id'] == 'scale':
					scale = float(attribs['value'])	

				elif attribs['id'] == 'color':
					color = int(attribs['value'].split(',')[0]), int(attribs['value'].split(',')[1]), int(attribs['value'].split(',')[2])

				elif attribs['id'] == 'alpha':
					alpha = int(attribs['value'])

				elif attribs['id'] == 'end_scale':
					end_scale = float(attribs['value'])

				elif attribs['id'] == 'scale_change_freq':
					scale_change_freq = int(attribs['value'])

				elif attribs['id'] == 'scale_change_step':
					scale_change_step = float(attribs['value'])

				elif attribs['id'] == 'end_color':
					if attribs['value'] == '0':
						end_color = 0

					else:
						end_color = int(attribs['value'].split(',')[0]), int(attribs['value'].split(',')[1]), int(attribs['value'].split(',')[2])

				elif attribs['id'] == 'color_change_freq':
					color_change_freq = int(attribs['value'])

				elif attribs['id'] == 'color_change_step':
					color_change_step = int(attribs['value'])

				elif attribs['id'] == 'end_alpha':
					end_alpha = int(attribs['value'])

				elif attribs['id'] == 'alpha_change_freq':
					alpha_change_freq = int(attribs['value'])

				elif attribs['id'] == 'alpha_change_step':
					alpha_change_step = int(attribs['value'])
			template = Particle(life_frames, speed, surface_data, scale, color, alpha, end_scale, scale_change_freq, scale_change_step, end_color, color_change_freq, 
				color_change_step, end_alpha, alpha_change_freq, alpha_change_step, self) #create the new particle template

			self.particle_templates.append(template) #add the new particle template to the template list

	def createParticleSurface(self, attribs):
		"""

		Create the particle surface.

		@attribs L{Dictionnary} : attributes of the current surface property of the particle

		"""

		surface_data = None
		
		if attribs['value'] == 'rect':
			#get the width and the height of the rect
			width = int(attribs['rect'].split(',')[0])
			height = int(attribs['rect'].split(',')[1])

			surface_data = ['rect', (width, height)]

		elif attribs['value'] == 'circle':
			radius = int(attribs['radius'])

			surface_data = ['circle', radius]

		else:
			#the surface particle is an image
			img = pygame.image.load(attribs['value']).convert()

			#check the colorkey argument
			if attribs['colorkey'] == 'auto':
				#auto colorkey settings, so use the top left pixel color as the colorkey
				img.set_colorkey(img.get_at((0, 0)))

			else:
				r, g, b = attribs['colorkey'].split(',')
	
				img.set_colorkey((int(r), int(g), int(b)))

			surface_data = ['img', img]

		return surface_data

	def emit(self, amount, angle_range):
		"""

		Emit a given amount of particles from the emitter.

		@amout L{Int} : how many particles to create
		@angle_range L{Tuple} : angle range for calculating particle velocity components

		"""
	
		count = 0
		while count < amount:
			t_choice = random.randint(0, len(self.particle_templates) - 1) #randomly choose between one of the templates in the given XML file 

			new_particle = copy.copy(self.particle_templates[t_choice]) #create the particle with the choosen template

			#set the particle with initial position and a random angle
			new_particle.setPosition(self.emitter.getLocation())
			new_particle.setAngle(random.randint(angle_range[0], angle_range[1]))

			self.particles.append(new_particle)

			count += 1

	def removeParticle(self, particle):
		"""

		Remove a particle.

		@particle L{Particle} : particle to remove

		"""

		self.particles.remove(particle)

	def update(self):
		"""

		Update the particles.

		"""

		for p in self.particles:
			p.update()

	def draw(self, screen):
		"""
			
		Draw the particles.

		@screen L{pygame.Surface} : surface to draw the particle on

		"""

		for p in self.particles:
			p.draw(screen)

	def setEmitterLocation(self, loc):
		"""

		Set new location for the engine emitter.

		@loc L{Tuple} : new location

		"""

		self.emitter.setLocation(loc)
